import cv2
import numpy as np

# 读取图片
image = cv2.imread("../boxs.png")  # 替换为实际的图片路径
if image is None:
    print("无法加载图片！")
    exit(-1)

# 将图像从BGR颜色空间转换到HSV颜色空间
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

# 定义蓝色在HSV颜色空间中的阈值范围
lower_blue = np.array([105, 190, 180])
upper_blue = np.array([115, 255, 255])

# 根据阈值创建掩膜，分离出蓝色区域
mask = cv2.inRange(hsv, lower_blue, upper_blue)

# 对掩膜进行形态学操作（开运算，去除噪声并平滑区域边界）
kernel = np.ones((3, 3), np.uint8)
opened_mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)

# 查找蓝色区域中的轮廓
contours, _ = cv2.findContours(opened_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

print(f"检测到的轮廓数量: {len(contours)}")

# 定义参考矩形的参数
REF_AREA = 200.0 * 280.0
REF_RATIO = 200.0 / 280.0
AREA_THRESHOLD = 0.5  # 面积误差阈值（50%）
RATIO_THRESHOLD = 0.2  # 长宽比误差阈值（20%）

# 遍历轮廓
for i, contour in enumerate(contours):
    # 计算凸包
    hull = cv2.convexHull(contour)

    # 获取最小外接旋转矩形
    minRect = cv2.minAreaRect(hull)
    rectPoints = cv2.boxPoints(minRect)
    rectPoints = np.int32(rectPoints)  # 修改为 np.int32

    # 面积筛选
    area = minRect[1][0] * minRect[1][1]
    area_diff = abs(area - REF_AREA) / REF_AREA
    if area_diff > AREA_THRESHOLD:
        print(f"矩形 {i + 1} 的面积差距过大，跳过。")
        continue

    # 绘制轮廓 黄色
    cv2.drawContours(image, [contour], -1, (0, 255, 255), 2)
    # 绘制凸包 绿色
    cv2.drawContours(image, [hull], -1, (0, 255, 0), 2)
    # 绘制最小外接旋转矩形 红色
    cv2.polylines(image, [rectPoints], True, (0, 0, 255), 2)

    # 提取旋转矩形区域并保存
    rotationMatrix = cv2.getRotationMatrix2D(minRect[0], minRect[2], 1.0)
    rotatedImage = cv2.warpAffine(image, rotationMatrix, (image.shape[1], image.shape[0]), flags=cv2.INTER_CUBIC)

    rectSize = (int(minRect[1][0]), int(minRect[1][1]))
    if minRect[2] < -45.0:
        rectSize = (rectSize[1], rectSize[0])
    
    cropped = cv2.getRectSubPix(rotatedImage, rectSize, minRect[0])

    # 保存裁剪后的图像
    cropped_filename = f"rotated_rectangle_{i + 1}.png"
    cv2.imwrite(cropped_filename, cropped)
    print(f"矩形 {i + 1} 裁剪图像已保存为 {cropped_filename}")

# 显示结果图像
cv2.imshow("Blue Rectangles Detection", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
